<template>
  <div>
    <el-container class="container">
      <!-- 头部 -->
      <!-- <el-header class="header" height="50px">Header</el-header> -->
      <el-container>
        <!-- 左侧边栏 -->
        <el-aside id="aside-left" width="101px">
          <draggable :sort="false" @end="onDragEnd">
            <div class="aside-left-list" flag="0">
              <img
                class="dataSet"
                draggable="false"
                src="@/assets/images/dataSet.svg"
              />
              <div class="dataSetDiv">数据集</div>
            </div>
          </draggable>
          <draggable :sort="false" @end="onDragEnd">
            <div class="aside-left-list" flag="1">
              <img
                class="dataProcessing"
                draggable="false"
                src="@/assets/images/dataProcessing.svg"
              />
              <div class="text">数据加工</div>
            </div>
          </draggable>
          <div class="aside-left-list" flag="2">
            <img
              class="algorithmModel"
              draggable="false"
              src="@/assets/images/algorithmModel.svg"
            />
            <div>算法模型</div>
          </div>
        </el-aside>
        <!-- 算法模型扩展 -->
        <el-aside
          v-show="isShowAlgorithmModelList"
          id="algorithmModel-list"
          width="300px"
        >
          <div
            v-for="item in AlgorithmModelList"
            :key="item.id"
            class="algorithmModel-list-children"
          >
            <!-- 标题 -->
            <div class="title">{{ item.title }}</div>
            <!-- 算法模型 -->
            <div>
              <draggable
                :sort="false"
                style="display: flex; flex-wrap: wrap"
                @end="onDragEnd"
              >
                <div
                  v-for="i in item.children"
                  :key="i.id"
                  :algorithmId="i.id"
                  class="aside-left-list"
                  flag="2"
                  style="width: 100px; margin: 10px"
                >
                  <img
                    :src="i.picName ? getPicName(i.picName) : ''"
                    style="width: 40px"
                  />
                  <div style="font-size: 14px">{{ i.name }}</div>
                </div>
              </draggable>
            </div>
          </div>
        </el-aside>
        <!-- 主体 -->
        <el-container>
          <el-container>
            <el-main id="main" @dragover="handleDragOver">
              <!-- 右键数据集 -->
              <div
                v-show="rightClickMenuType === 1"
                id="dsSet-right-click"
                :style="{ position: 'absolute', left: left, top: top }"
                class="dscolor"
              >
                <div class="children" @click="del">删除</div>
                <div
                  v-show="!isDataIdExist"
                  class="children"
                  @click="showFileUpload"
                >
                  上传数据
                </div>
                <div
                  v-show="isDataIdExist"
                  class="children"
                  @click="showFileData"
                >
                  查看数据
                </div>
                <div
                  v-show="isDataIdExist"
                  class="children"
                  @click="showfieldDialog = true"
                >
                  字段设置
                </div>
                <div
                  v-if="!isDataIdExist"
                  class="children"
                  @click="navigateToDataView()"
                >
                  连接数据库
                </div>
                <div
                  v-show="isDataIdExist"
                  class="children"
                  @click="restFileUpload"
                >
                  重置数据
                </div>
              </div>
              <!-- 右键数据加工 -->
              <div
                v-show="rightClickMenuType === 2"
                id="dsSet-right-click"
                :style="{ position: 'absolute', left: left, top: top }"
                class="dscolor"
              >
                <div class="children" @click="del">删除</div>
                <div class="children" @click="dataProcess()">数据加工</div>
              </div>
              <!-- 右键算法模型 -->
              <div
                v-show="rightClickMenuType === 3"
                id="dsSet-right-click"
                :style="{ position: 'absolute', left: left, top: top }"
                class="dscolor"
              >
                <div class="children" @click="del">删除</div>
                <div class="children" @click="chooseField">选择字段</div>
                <div class="children" @click="execute">执行</div>
              </div>
              <!-- 空div -->
              <div class="empty"></div>
              <div
                v-for="(value, key) in renderAllData"
                :id="value.id"
                :key="key"
                :algorithmid="value.AlgorithmId"
                :draggable="true"
                :flag="value.flag"
                :style="{
                  top: value.posY,
                  left: value.posX,
                  position: 'absolute',
                }"
                class="aside-left-list valueNode"
                @dragend="renderDragEnd"
              >
                <!--                {{getNodePicUrl(value.AlgorithmId)}}-->
                <img
                  :src="getNodePicUrl(value, value.flag)"
                  class="dataSet"
                  draggable="false"
                />
                <div class="dataSetDiv">
                  {{ getNodePicUrl(value, value.flag, true) }}
                </div>
              </div>
            </el-main>
            <!-- 底部 -->
            <el-footer id="footer" height="150px"></el-footer>
          </el-container>
          <!-- 右侧边栏 -->
          <el-aside id="aside-right" width="200px">
            <el-row class="header">
              <el-col :span="22" class="back myIcon">
                <el-tooltip content="保存" placement="bottom-start">
                  <!-- <el-icon :size="20" @click="saveScene">
                    <FolderChecked />
                  </el-icon> -->
                  <svg
                    t="1701308833546"
                    class="icon"
                    viewBox="0 0 1024 1024"
                    version="1.1"
                    xmlns="http://www.w3.org/2000/svg"
                    p-id="4262"
                    width="20"
                    height="20"
                    style="display: flex"
                    @click="saveScene"
                  >
                    <path
                      d="M586.47 606.03h-278c-17.47 0-31.63 14.16-31.63 31.63s14.16 31.63 31.63 31.63h278c17.47 0 31.63-14.16 31.63-31.63s-14.16-31.63-31.63-31.63z"
                      fill="#404040"
                      p-id="4263"
                    ></path>
                    <path
                      d="M899.59 319.54L686.92 103a31.647 31.647 0 0 0-22.57-9.47H146.98c-17.47 0-31.63 14.16-31.63 31.63v773.68c0 17.47 14.16 31.63 31.63 31.63h730.05c17.47 0 31.63-14.16 31.63-31.63V341.7c0-8.29-3.26-16.25-9.07-22.16zM337.86 156.79h219.21v219.2H337.86v-219.2z m507.53 710.42H178.61V156.79h95.99v250.83c0 17.47 14.16 31.63 31.63 31.63h282.48c17.47 0 31.63-14.16 31.63-31.63V156.79h30.75l194.3 197.84v512.58z"
                      fill="#404040"
                      p-id="4264"
                    ></path>
                  </svg>
                </el-tooltip>
                <el-tooltip content="清除" placement="bottom-end">
                  <el-icon :size="20" @click="clearScene" class="icon-del">
                    <Delete />
                  </el-icon>
                </el-tooltip>
                <el-tooltip content="返回" effect="light" placement="left">
                  <el-icon :size="20" class="icon" @click="close">
                    <Back />
                  </el-icon>
                </el-tooltip>
              </el-col>
            </el-row>
            <!-- 数据集右侧 -->
            <div v-show="activeFlag === '0'" class="ds-right">
              <!-- 选择文件 -->
              <div class="title">选择文件</div>
              <el-input
                v-model="queryFileName"
                clearable
                placeholder="请输入文件名"
                size="small"
                @input="queryAllFileList"
              ></el-input>
              <div class="fileList">
                <div
                  v-for="item in allFileList"
                  :id="item.id"
                  :key="item.id"
                  :class="['fileItem', { active: item.id === currentData.id }]"
                  @click="toggleFileData($event, item.name)"
                >
                  <img :src="getPicURL(item.name)" style="width: 10px" />
                  {{ item.name }}
                </div>
              </div>
              <div class="title">选择数据源</div>
              <div class="fileList">
                <el-tree
                  ref="treeRef"
                  :data="dsData"
                  :default-expand-all="true"
                  :props="defaultProps"
                  highlight-current
                  node-key="nodeID"
                  @node-click="toggledsData"
                >
                  <template #default="{ node, data }">
                    <span class="custom-tree-node">
                      <span class="tree_nodei_icon">
                        <img
                          v-if="data.nodeType === '0'"
                          alt=""
                          class="tree_nodei_img"
                          src="@/assets/images/rxtree_parent_focus.png"
                        />
                        <img
                          v-else
                          alt=""
                          class="tree_nodei_img"
                          src="@/assets/images/rxtree_child_focus.png"
                        />
                      </span>
                      <span>{{ node.label }}</span>
                    </span>
                  </template>
                </el-tree>
              </div>
            </div>
            <div v-show="activeFlag === '2'" class="right_algorithm_container">
              <div class="algorithm_title">{{ currentAlgorithm.name }}</div>
              <div v-if="modelConfig?.tabInfo?.taskSet === '1'">
                <div class="algorithm_line"></div>
                <div style="padding: 5px 10px; font-size: 14px">任务选择</div>
                <el-form
                  ref="taskChooseRef"
                  :model="taskChooseForm"
                  label-position="top"
                >
                  <el-form-item label="选择模型任务:" prop="modelTask">
                    <el-radio-group
                      v-model="taskChooseForm.modelTask"
                      size="small"
                    >
                      <el-radio label="isTrain">训练</el-radio>
                      <el-radio label="isApply">应用</el-radio>
                      <el-radio label="isAllTask">全部</el-radio>
                    </el-radio-group>
                  </el-form-item>
                  <el-form-item label="选择模型名称:" prop="modelName">
                    <el-input
                      v-model="taskChooseForm.modelName"
                      placeholder="请输入模型名称"
                    >
                      <template #append>浏览</template>
                    </el-input>
                  </el-form-item>
                </el-form>
              </div>

              <div v-if="modelConfig?.tabInfo?.paramSet === '1'">
                <div class="algorithm_line"></div>
                <div style="padding: 5px 10px; font-size: 14px">参数配置</div>
                <el-form
                  ref="AlgorithmForm"
                  :model="paramsForm"
                  :rules="paramsRules"
                  label-position="top"
                >
                  <el-form-item
                    v-for="item in modelConfig?.paramInfo"
                    :key="item"
                    :label="item.paramName"
                    :prop="item.paramCode"
                  >
                    <template #label>
                      <span
                        >{{ item.paramName }}
                        <el-tooltip
                          :content="item.paramDescription"
                          effect="dark"
                          placement="left-start"
                          style="width: 110px"
                        >
                          <el-icon><QuestionFilled /></el-icon>
                        </el-tooltip>
                      </span>
                    </template>
                    <el-select
                      v-if="item.disType === 'combobox'"
                      v-model="paramsForm[item.paramCode]"
                      :placeholder="`请选择${item.paramName}`"
                    >
                      <el-option
                        v-for="(option, index) in item?.disValue?.split('|') ||
                        []"
                        :key="index"
                        :label="option"
                        :value="item?.value?.split('|')[index]"
                      />
                    </el-select>
                    <el-input
                      v-else-if="item.disType === 'text'"
                      v-model="paramsForm[item.paramCode]"
                      :placeholder="`请填写${item.paramName}`"
                    ></el-input>
                  </el-form-item>
                </el-form>
              </div>

              <div v-if="modelConfig?.tabInfo?.outputSet === '1'">
                <div class="algorithm_line"></div>
                <div style="padding: 5px 10px; font-size: 14px">输出设置</div>
                模型文件名: LogisticRegression_
                <el-input v-model="outputSet"></el-input>
              </div>
            </div>
          </el-aside>
        </el-container>
      </el-container>
    </el-container>
    <!-- 文件上传弹框 -->
    <el-dialog
      id="fileDialog"
      v-model="dialogVisible"
      :close-on-click-modal="false"
      width="40%"
    >
      <template #header>上传文件</template>
      <el-divider />
      <span class="span">选择上传文件类型</span>
      <el-form ref="fileForm" v-model="fileForm" class="father">
        <el-radio-group v-model="fileForm.type" class="fileRadio1">
          <div class="fileRadio1-demo">
            <img class="pic" src="@/assets/images/file_excel.png" />
            <el-radio label=".xls,.xlsx" size="large">Excel</el-radio>
          </div>
          <div class="fileRadio1-demo">
            <img class="pic" src="@/assets/images/txt.png" />
            <el-radio label=".txt" size="large">Txt</el-radio>
          </div>
          <div class="fileRadio1-demo">
            <img class="pic" src="@/assets/images/csv.png" />
            <el-radio label=".csv" size="large">Csv</el-radio>
          </div>
        </el-radio-group>
        <div v-show="fileForm.type !== '.xls,.xlsx'">
          <span class="span">选择数据文件的分隔符</span>
          <div style="margin-left: 75px">
            <el-radio-group v-model="fileForm.spliter" class="fileRadio2">
              <el-radio label="," size="large" @click="fileForm.myspliter = ''"
                >逗号 ( , )
              </el-radio>
              <el-radio label=";" size="large" @click="fileForm.myspliter = ''"
                >分号 ( ; )
              </el-radio>
              <el-radio label="|" size="large" @click="fileForm.myspliter = ''"
                >竖线 ( | )
              </el-radio>
              <el-radio label="0" size="large">
                自定义分隔符
                <el-input
                  v-model="fileForm.myspliter"
                  maxlength="4"
                  placeholder="自定义行/列作为表头"
                  style="width: 150px"
                ></el-input>
              </el-radio>
            </el-radio-group>
          </div>
          <div></div>
        </div>
        <div style="display: flex">
          <span class="span">表头选择</span>
          <el-radio-group v-model="fileForm.direction" class="fileRadio2">
            <el-radio label="1" size="large">行</el-radio>
            <el-radio label="2" size="large">列</el-radio>
          </el-radio-group>
        </div>
        <el-radio-group v-model="fileForm.header" class="fileRadio3">
          <el-radio label="1" size="large" @click="fileForm.count = ''"
            >以首行/首列作为表头
          </el-radio>
          <el-radio label="2" size="large">
            <el-tooltip
              class="box-item"
              content="表头上面不要有空行"
              effect="dark"
              placement="top"
            >
              <el-input
                v-model.number="fileForm.count"
                :disabled="fileForm.header !== '2'"
                placeholder="自定义行/列作为表头"
              ></el-input>
            </el-tooltip>
          </el-radio>
        </el-radio-group>
        <div style="display: flex">
          <span class="span">选择文件</span>
          <el-upload
            ref="upload-demo"
            :accept="fileForm.type"
            :auto-upload="false"
            :before-remove="beforeRemove"
            :before-upload="beforeUpload"
            :file-list="fileList"
            :http-request="uploadFile"
            :limit="1"
            :on-change="handleChange"
            :on-exceed="handleExceed"
            :on-preview="handlePreview"
            :on-remove="handleRemove"
            :on-success="uploadSuccess"
            action=""
            class="upload-demo"
            drag
          >
            <el-icon class="el-icon--upload">
              <upload-filled />
            </el-icon>
            <div class="el-upload__text">
              拖动文件到这里或者 <em>点击上传</em>
            </div>
            <template #tip>
              <div class="el-upload__tip"></div>
            </template>
          </el-upload>
        </div>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-divider />
          <el-button @click="dialogVisible = false">关闭</el-button>
          <el-button @click="manualUpload">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 查看文件弹窗 -->
    <el-dialog
      v-model="showFileTableDialog"
      :close-on-click-modal="false"
      :title="currentData.title"
      width="70%"
    >
      <div style="width: 90%; margin: 10px auto; overflow: auto">
        <el-table
          :border="true"
          :data="currentData.valueList"
          empty-text="空"
          height="500px"
          show-overflow-tooltip
          stripe
        >
          <el-table-column
            v-for="(item, index) in currentData.keyList"
            :key="index"
            :label="item"
            :property="item"
            align="center"
            resizable
            show-overflow-tooltip
          >
            <template #header>
              <el-tooltip
                :content="item"
                class="box-item"
                effect="dark"
                placement="top"
              >
                <div
                  style="
                    overflow: hidden;
                    white-space: nowrap;
                    text-overflow: ellipsis;
                  "
                >
                  {{ item }}
                </div>
              </el-tooltip>
            </template>
          </el-table-column>
          <!-- :width="fitHeaderLength(item)" -->
        </el-table>
      </div>
      <!-- 分页 -->
      <div
        v-if="this.currentData.title === '查看数据'"
        style="width: 100%; padding: 10px; box-sizing: border-box"
      >
        <el-pagination
          :current-page="currentData.currentPage"
          :page-size="currentData.pageSize"
          :page-sizes="[20, 50, 100]"
          :total="currentData.total"
          layout="total, sizes, prev, pager, next"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          @prev-click="prevPage"
          @next-click="nextPage"
        >
        </el-pagination>
      </div>
    </el-dialog>
    <!-- 字段设置弹窗 -->
    <el-dialog
      v-model="showfieldDialog"
      :close-on-click-modal="false"
      class="fieldDialog"
      style="height: 480px"
      title="字段设置"
      width="600"
    >
      <el-row style="height: 300px; overflow: auto">
        <el-col
          v-for="item in fieldData"
          :key="item.id"
          :offset="3"
          :span="18"
          class="fieldCol"
        >
          <el-tooltip
            :content="item.colComment"
            effect="light"
            placement="top"
            style="width: 100px"
          >
            <span class="fieldSpan">{{ item.colComment }}</span>
          </el-tooltip>
          <el-select
            v-model="item.colTypeName"
            class="fieldSelect"
            placeholder="请选择类型"
            size="large"
            @change="handleSettingSelect(item)"
          >
            <el-option label="文本型" value="STRING" />
            <el-option label="数值型" value="NUMERIC" />
            <el-option label="枚举型" value="ENUM" />
            <el-option label="日期型 yyyy" value="DATE yyyy" />
            <el-option label="日期型 yyyy年" value="DATE yyyy年" />
            <el-option label="日期型 yyyyMM" value="DATE yyyyMM" />
            <el-option label="日期型 yyyy年MM月" value="DATE yyyy年MM月" />
            <el-option label="日期型 yyyy-MM" value="DATE yyyy-MM" />
            <el-option label="日期型 yyyy/MM" value="DATE yyyy/MM" />
            <el-option label="日期型 yyyyMMdd" value="DATE yyyyMMdd" />
            <el-option
              label="日期型 yyyy年MM月dd日"
              value="DATE yyyy年MM月dd日"
            />
            <el-option label="日期型 yyyy-MM-dd" value="DATE yyyy-MM-dd" />
            <el-option label="日期型 yyyy/MM/dd" value="DATE yyyy/MM/dd" />
            <el-option label="日期型 HH:mm:ss" value="DATE HH:mm:ss" />
            <el-option label="日期型 HH时mm分ss秒" value="DATE HH时mm分ss秒" />
            <el-option
              label="日期型 yyyyMMdd HH:mm:ss"
              value="DATE yyyyMMdd HH:mm:ss"
            />
            <el-option
              label="日期型 yyyy-MM-dd HH:mm:ss"
              value="DATE yyyy-MM-dd HH:mm:ss"
            />
          </el-select>
        </el-col>
      </el-row>
      <template #footer>
        <span class="dialog-footer">
          <el-divider />
          <el-button @click="closeFieldSet">关闭</el-button>
          <el-button type="primary" @click="showfieldDialog = false"
            >确定</el-button
          >
        </span>
      </template>
    </el-dialog>

    <MyDialog
      :dataSource="fieldData"
      :destVarData="configParams[currentDomId]?.destVar"
      :info="modelConfig?.tabInfo || {}"
      :isShow="showDialog"
      :varListData="configParams[currentDomId]?.varList"
      @dialogClose="dialogClose"
      @getParam="getParam"
    ></MyDialog>

    <el-dialog
      v-model="saveSceneDialog"
      :close-on-click-modal="false"
      style="padding: 10px"
      title="保存场景"
    >
      <el-form v-model="saveSceneForm">
        <el-form-item label="场景名称" prop="sceneName">
          <el-input v-model="saveSceneForm.sceneName"></el-input>
        </el-form-item>
        <el-form-item label="场景介绍" prop="sceneDesc">
          <el-input
            v-model="saveSceneForm.sceneDesc"
            type="textarea"
          ></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="closeSaveScene">取消</el-button>
          <el-button type="primary" @click="confirmSaveScene">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 执行弹框  -->
    <ExeResult
      :exeResultdialog="exeResultdialog"
      :queryParams="executeParams"
      @close="closeExeResult"
    ></ExeResult>
  </div>
</template>
<script>
import {
  executeAlgorithm,
  fileUpload,
  getAlgorithmModelList,
  getDataModelList,
  getSceneDefine,
  queryAllFileList,
  queryDataSourceColumn,
  queryDsDataList,
  queryModelConfig,
  saveSceneDefine,
  showFileData,
} from "@/services/scene";
import { VueDraggableNext } from "vue-draggable-next";
import { UploadFilled } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import LeaderLine from "@/utils/leader-line.min.js";
import MyDialog from "@/components/MyDialog";
import { Canvg } from "canvg";
import html2canvas from "html2canvas";
import ExeResult from "@/views/BI/ExeResult.vue";
let isKeep = true;
export default {
  components: {
    draggable: VueDraggableNext,
    UploadFilled,
    MyDialog,
    ExeResult,
  },
  props: ["id"],
  computed: {
    isDataIdExist() {
      return this.currentData.id;
    },
  },
  data() {
    return {
      picURL: {
        excel: require("@/assets/images/file_excel.png"),
        txt: require("@/assets/images/txt.png"),
        csv: require("@/assets/images/csv.png"),
      },
      mouseX: 0,
      mouseY: 0,
      left: 0,
      top: 0,
      //连线
      lines: [],
      allLines: [],
      startElement: null,
      endElement: null,
      chooseElements: [],
      // 是否显示算法模型的列表
      isShowAlgorithmModelList: false,
      //右键菜单类型 1:数据集，2:数据加工，3：算法模型,
      rightClickMenuType: 0,
      //右键画布中dom 节点的id
      currentDomId: "",
      // 文件上传弹框
      dialogVisible: false,
      //临时文件列表
      tempFileList: [],
      // 文件查看弹框
      showFileTableDialog: false,
      // 字段设置弹窗
      showfieldDialog: false,
      //文件单选
      fileForm: {
        type: ".xls,.xlsx",
        header: "1",
        direction: "1",
        count: "",
        spliter: "",
        myspliter: "",
      },
      fileList: [],
      AlgorithmModelList: [],
      //数据集个数
      dataSetCount: 0,
      //右侧输入框绑定的文件名
      queryFileName: "",
      //当前查看文件
      currentData: {
        title: "",
        type: "",
        id: "",
        fileName: "",
        //文件的数据
        valueList: [],
        //表头
        keyList: [],
        total: 0,
        currentPage: 1,
        pageSize: 10,
      },
      //右侧所有文件列表
      allFileList: [],
      //myDialog显示隐藏
      showDialog: false,
      //数据源
      dsData: [],
      defaultProps: {
        label: "nodeName",
        children: "children",
      },
      //右键画布中算法模型，给dialog传值
      currentDialogData: {
        id: "",
        dataForSelect: [],
        rightSelect: [],
      },
      //activeFlag.现在激活的数据集，数据加工，算法模型的哪个，0，1，2
      activeFlag: "",
      //点击算法模型的的画布内容后得到该算法的id和name，在右侧显示他的配置
      currentAlgorithm: {
        id: "",
        name: "",
      },
      //任务选择form
      taskChooseForm: {
        modelTask: "isTrain",
        modelName: "",
      },
      //右侧任务选择，参数配置，输出设置
      modelConfig: {},
      //模型参数设置output
      outputSet: `${new Date().getTime()}.mdl`,
      //右侧参数设置form v-model数据
      paramsForm: {},
      //右侧边栏参数设置form rule规则
      paramsRules: {},
      //数据集-字段设置修改后的-参数列表
      fieldData: [],
      // 数据集-原始-参数列表
      fieldOrignData: [],
      //从参数配置dialog弹窗拿到的数据
      configParams: {},
      //allData ,存所有的line和节点，对象内key是时间戳，
      allData: { lines: {} },
      //保存场景信息
      saveSceneForm: {},
      //保存场景信息dialog显示与隐藏
      saveSceneDialog: false,
      //截图文件
      screenPic: "",
      //当前场景的id
      sceneId: undefined,
      //算法模型右侧，表单内容，校验，字段设置dialog的配置信息，是一个{时间戳:{}}
      allModelConfig: {},
      //渲染的方法源
      renderAllData: {},
      exeResultdialog: false, //弹框状态
      //执行的请求参数
      executeParams: {},
    };
  },
  //因为用了keepalive缓存了进入当前路由触发 让svg显示
  activated() {
    this.getDataModelList();
    if (isKeep) {
      this.renderLines(this.allLines);
      //重新刷新数据源列表
    } else {
      const footer = document.querySelectorAll("#footer .log");
      footer.forEach((e) => {
        e.remove();
      });
      const canvasDom = document.querySelectorAll("#main .aside-left-list");
      canvasDom.forEach((e) => {
        // console.log(e,e.classList.contains('valueNode'),'classList')
        if (!e.classList.contains("valueNode")) {
          e.remove();
        }
      });
      this.currentAlgorithm = {};
      this.taskChooseForm = {
        modelTask: "isTrain",
        modelName: "",
      };
      this.modelConfig = {};
      this.activeFlag = "";
      this.allData = { lines: {} };
      this.$store.dispatch("setnewAvgdatas", []);
      //根据场景id请求具体参数
      if (this.id) {
        this.querySceneDefine();
      } else {
        this.allLines = [];
        //获得画布中的算法节点数组，并删除他们
        this.renderAllData = {};
      }
    }
  },
  //组件内路由守卫
  beforeRouteEnter(to, from, next) {
    if (from.name === "SceneView" || from.fullPath === "/") {
      isKeep = false;
    }
    next();
  },
  //因为用了keepalive缓存了离开当前路由触发 让svg线隐藏
  deactivated() {
    this.dataSetCount = 0;
    isKeep = true;
    if (this.lines.length !== 0) {
      for (let i = 0; i < this.lines.length; i++) {
        this.lines[i].remove();
      }
      this.lines = [];
    }
    // this.$store.state.avg =  [];
    // this.$store.state.historys = [];
  },
  methods: {
    //根据lines中的值，渲染生成line
    renderLines(lines) {
      lines.forEach((item) => {
        let styleOption = {
          color: "rgb(2,167,240)", // 指引线颜色
          size: 3, // 线条尺寸
          path: "straight", // straight,arc,fluid,magnet,grid
          startSocket: "auto", //在指引线开始的地方从元素左侧开始
          endSocket: "auto", //在指引线开始的地方从元素右侧结束
          endPlug: "arrow2", // 指引线结束点的样式 hand,disc
          startLabel: "",
          middleLabel: "",
          endLabel: "",
          dash: true, //虚线
          hide: true, // 绘制时隐藏，默认为false，在初始化时可能会出现闪烁的线条
          outLineColor: "blue",
        };
        //创建实例
        const line = new LeaderLine(item[0], item[1], styleOption);
        line.show();
        this.lines.push(line);
      });
      this.allLines = [];
      this.lines.forEach((item) => {
        this.allLines.push([item.start, item.end]);
      });
      this.$store.commit("updateLines", this.allLines);
    },
    dialogClose(status) {
      this.showDialog = status;
    },
    getParam(params) {
      console.log(
        "从mydialog传来的值",
        params,
        this.allData[this.currentDomId].config
      );

      this.allData[this.currentDomId].config = Object.assign(
        this.allData[this.currentDomId].config,
        params
      );
      this.configParams[this.currentDomId] = params;
    },
    getPicName(name) {
      return require(`@/assets/images/AlgorithmMode/${name}.png`);
    },
    //算法执行
    async execute() {
      try {
        //执行的数据集，数据加工，算法的节点数组
        let executeLine = [];
        //数据加工的id
        //跟据line数组，一级一级想上找，找到整条线路
        let dataProcessing = "";
        const tempLines = Object.assign({}, this.allData.lines);
        for (const key in tempLines) {
          if (tempLines[key].stopNode === this.currentDomId) {
            console.log(tempLines, "tempLines");
            executeLine.push(tempLines[key].startNode, tempLines[key].stopNode);
            dataProcessing = tempLines[key].startNode;
          }
        }
        for (const key in tempLines) {
          if (tempLines[key].stopNode === dataProcessing) {
            executeLine.unshift(tempLines[key].startNode);
          }
        }
        //整理保存接口的数据加工的
        const process = JSON.parse(localStorage.getItem("vuex")).avg[0];
        for (const processKey in process) {
          this.allData[processKey].config = process[processKey];
        }

        const result = await executeAlgorithm({
          nodeList: executeLine,
          nodeParam: this.allData,
        });
        this.executeParams = result.respData;
        // localStorage.setItem("respData", JSON.stringify(result.respData));
        this.exeResultdialog = true;
      } catch (e) {
        console.error(e);
        ElMessage({
          type: "error",
          message: e.respMessage,
        });
      }
    },
    //关闭算法执行弹窗
    closeExeResult() {
      this.exeResultdialog = false;
    },
    onDragEnd(event) {
      event.preventDefault();
      // console.log(event.originalEvent.target);
      // 获取被拖拽的图片元素
      const draggedItem = event.item;
      if (draggedItem.children[1].innerHTML === "算法模型") return;
      // 创建一个新的图片元素副本
      const clonedItem = draggedItem.cloneNode(true);
      clonedItem.style.position = "absolute";
      const posY = this.mouseY - draggedItem.offsetHeight / 2 + "px";
      const posX = this.mouseX - draggedItem.offsetWidth / 2 + "px";
      const flag = clonedItem.getAttribute("flag");
      clonedItem.style.top = posY;
      clonedItem.style.left = posX;
      if (clonedItem.getAttribute("flag") === "0") {
        this.dataSetCount++;
      }
      if (clonedItem.getAttribute("flag") === "0" && this.dataSetCount > 1) {
        return this.$message.error("数据集只能存在一个");
      }
      //clonedItem.style.transition = 'left 0.1s, top 0.1s';
      clonedItem.draggable = true;
      const timestamp = +new Date() + "";
      clonedItem.id = timestamp;
      //拖拽结束，向数据对象中添加节点，
      // console.log(this.allData, 'allData', typeof timestamp)
      // 将克隆元素添加到页面中
      if (this.checkDomPosition(clonedItem)) {
        document.querySelector("#main").appendChild(clonedItem);
        if (flag === "0") {
          this.allData[timestamp] = {
            id: timestamp,
            posX,
            posY,
            flag,
            algorithmType: "2",
            algorithmTypeName: "graphDs",
            AlgorithmId: "",
          };
          this.createLog("数据集 创建成功！");
        } else if (flag === "1") {
          this.allData[timestamp] = {
            id: timestamp,
            posX,
            posY,
            flag,
            algorithmType: "20",
            algorithmTypeName: "graphDa",
            AlgorithmId: "",
          };
          this.createLog("数据加工 创建成功！");
        } else if (flag === "2") {
          this.allData[timestamp] = {
            id: timestamp,
            posX,
            posY,
            flag,
            algorithmType: "4",
            algorithmTypeName: "graphDLa",
            AlgorithmId: clonedItem.getAttribute("AlgorithmId"),
          };
          this.createLog("算法模型 创建成功！");
          const algorithmId = clonedItem.getAttribute("algorithmId");
          this.getModelConfig(algorithmId);
          this.currentAlgorithm = this.getRightAlgorithmName(algorithmId);
        }
        this.mouseX = 0;
        this.mouseY = 0;
      } else {
        this.$message.error("请拖拽到中间区域");
        this.dataSetCount = 0;
        return;
      }
      this.setNodeConfig(clonedItem);
    },

    //单独抽离出绑定的拖拽，连线，右键事件
    setNodeConfig(itemNode) {
      //给克隆元素绑定拖拽事件
      itemNode.addEventListener("dragend", (e) => {
        this.rightClickMenuType = 0;
        let x = e.clientX;
        let y = e.clientY;
        let parentContainerRect = e.target.parentNode.getBoundingClientRect();
        const asideLeft = document.querySelector("#aside-left");

        let left = Math.max(
          0,
          Math.min(
            x - asideLeft.offsetWidth - e.target.offsetWidth / 2,
            parentContainerRect.width - e.target.offsetWidth
          )
        );
        let top = Math.max(
          0,
          Math.min(
            y - asideLeft.offsetTop - e.target.offsetHeight / 2,
            parentContainerRect.height - e.target.offsetHeight
          )
        );
        e.currentTarget.style.top = top + "px";
        e.currentTarget.style.left = left + "px";

        setTimeout(() => {
          this.lines.forEach((item) => {
            item.position();
          });
        }, 100);
      });
      //给克隆元素绑定点击连线事件
      itemNode.addEventListener("click", (e) => {
        const main = document.querySelector("#main");
        const list = main.querySelectorAll(".aside-left-list");
        list.forEach((item) => {
          item.classList.remove("active");
        });
        e.currentTarget.classList.add("active");
        if (!this.startElement) {
          this.startElement = e.currentTarget;
          const div = document.querySelector(".empty");
          this.endElement = div;
          this.createLine(e.currentTarget, div, true);
        } else {
          if (
            this.startElement.getAttribute("flag") ===
            e.currentTarget.getAttribute("flag")
          ) {
            return this.$message.error("同种之间不能相连");
          }
          if (this.startElement.getAttribute("flag") === "2") {
            return this.$message.error("算法模型不能作为第一个连接项");
          }
          if (
            this.startElement.getAttribute("flag") === "1" &&
            e.currentTarget.getAttribute("flag") === "0"
          ) {
            return this.$message.error("数据加工不能主动连接数据集");
          }
          this.endElement = e.currentTarget;
          this.lines[this.lines.length - 1].remove();
          this.lines.pop();
          this.createLine(this.startElement, this.endElement, true);
          this.startElement = null;
          this.endElement = null;
        }
        this.activeFlag = e.currentTarget.getAttribute("flag");
        this.currentDomId = itemNode.id;
        const algorithmId = itemNode.getAttribute("algorithmId");
        this.currentAlgorithm = this.getRightAlgorithmName(algorithmId);
      });
      //右键事件
      itemNode.addEventListener("contextmenu", (e) => {
        e.preventDefault();
        //绑定当前数据集的id
        if (e.target.tagName === "IMG") {
          const main = document.querySelector("#main");
          const list = main.querySelectorAll(".aside-left-list");
          list.forEach((item) => {
            item.classList.remove("active");
          });
          e.currentTarget.classList.add("active");

          this.currentDomId = e.target.parentNode.id;
          let left = e.target.getBoundingClientRect().left - 50;
          let top = e.target.getBoundingClientRect().top - 40;
          this.left = left + "px";
          this.top = top + "px";
          if (e.currentTarget.getAttribute("flag") === "0") {
            this.rightClickMenuType = 1;
          } else if (e.currentTarget.getAttribute("flag") === "1") {
            this.rightClickMenuType = 2;
          } else if (e.currentTarget.getAttribute("flag") === "2") {
            this.rightClickMenuType = 3;
            this.activeFlag = "2";
            this.currentDomId = itemNode.id;
            const algorithmId = itemNode.getAttribute("algorithmId");
            // this.getModelConfig(algorithmId);
            this.currentAlgorithm = this.getRightAlgorithmName(algorithmId);
          }
        }
      });
    },
    //根据模型ID请求模型配置
    async getModelConfig(id) {
      const res = await queryModelConfig({ algorithmID: id });
      if (res?.respStatus) {
        //渲染表单
        const modelForm = {};
        //表单规则
        const modelRules = {};
        res.respData.paramInfo.forEach((i) => {
          if (i.defaultValue) {
            modelForm[i.paramCode] = i.defaultValue;
          }
          if (i.prmFormat) {
            modelRules[i.paramCode] = [
              { pattern: i.prmFormat, message: i.prmFormatPrompt },
            ];
          }
        });
        this.paramsForm = modelForm;
        this.paramsRules = modelRules;
        this.modelConfig = res?.respData;
        let isTrain = false,
          isApply = false,
          isAllTask = false;
        let params = {
          isTrain,
          isApply,
          isAllTask,
          modelName: this.taskChooseForm.modelName,
          ...this.paramsForm,
          output: `LogisticRegression_${this.outputSet}`,
        };
        params[this.taskChooseForm.modelTask] = true;
        for (const key in this.allData) {
          if (this.allData[key].AlgorithmId == id) {
            this.allData[key].config = Object.assign(
              params,
              this.allData[key].config
            );
            this.allModelConfig[key] = {
              paramsForm: modelForm,
              paramsRules: modelRules,
              modelConfig: res?.respData,
            };
          }
        }
      } else {
        ElMessage({
          message: res?.respMessage || "获取算法参数设置信息失败",
          type: "error",
        });
      }
    },

    //获取模型name
    getRightAlgorithmName(data) {
      const arr = this.AlgorithmModelList;
      let name = "";
      let picName = "";

      function recursion(arr) {
        if (Array.isArray(arr)) {
          arr.forEach((i) => {
            if (typeof i == "object") {
              for (let iKey in i) {
                if (Array.isArray(i[iKey])) {
                  recursion(i[iKey]);
                } else {
                  if (i.id == data) {
                    name = i.name;
                    picName = i.picName;
                    return;
                  }
                }
              }
            }
          });
        }
      }

      recursion(arr);
      return { id: data, name, picName };
    },
    //检查被拖拽的元素位置是否正确
    checkDomPosition(domItem) {
      const asideLeft = document.querySelector("#aside-left");

      let top = parseFloat(domItem.style.top);
      let left = parseFloat(domItem.style.left);
      // console.log(top, left);
      let topMax = document.querySelector("#main").offsetHeight;
      let leftMax = document.querySelector("#main").offsetWidth + 100;
      // console.log(top, asideLeft.offsetTop);
      return top > 0 && left > 0 && top < topMax && left < leftMax;
    },
    //线的方
    createLine(start, end, addAllData) {
      let styleOption = {
        color: "rgb(2,167,240)", // 指引线颜色
        size: 3, // 线条尺寸
        path: "straight", // straight,arc,fluid,magnet,grid
        startSocket: "auto", //在指引线开始的地方从元素自动位置开始
        endSocket: "auto", //在指引线开始的地方从元素自动位置结束
        endPlug: "arrow2", // 指引线结束点的样式 hand,disc
        startLabel: "",
        middleLabel: "",
        endLabel: "",
        dash: true, //虚线
        hide: true, // 绘制时隐藏，默认为false，在初始化时可能会出现闪烁的线条
        outLineColor: "blue",
      };
      // let animOptions = {};
      //创建实例
      const line = new LeaderLine(start, end, styleOption);
      line.show();
      this.lines.push(line);
      if (end !== document.querySelector(".empty")) {
        this.allLines.push([line.start, line.end]);
        if (addAllData) {
          this.allData.lines[new Date().getTime()] = {
            startNode: line.start.id,
            stopNode: line.end.id,
          };
        }
      }
      this.$store.commit("updateLines", this.allLines);
    },
    handleDragOver(event) {
      event.preventDefault();
      this.mouseX = event.offsetX;
      this.mouseY = event.offsetY;
    },
    del() {
      this.$store.state.newAvg = []; //之前的avg 清空
      this.dataSetCount = 0;
      //获取要被删除的元素
      const delElement = document.getElementById(this.currentDomId);
      if (this.lines.length !== 0) {
        for (let i = this.lines.length - 1; i >= 0; i--) {
          if (
            this.lines[i].start === delElement ||
            this.lines[i].end === delElement
          ) {
            this.lines[i].remove();
            this.lines.splice(i, 1);
          }
          let allLines = this.allData.lines;
          for (const allLinesKey in allLines) {
            if (
              allLines[allLinesKey].startNode === delElement.id ||
              allLines[allLinesKey].stopNode === delElement.id
            ) {
              delete allLines[allLinesKey];
            }
          }
          let nodeArr = this.allData;
          for (const nodeArrKey in nodeArr) {
            if (nodeArrKey === delElement.id) {
              delete nodeArr[nodeArrKey];
            }
          }
        }
        this.allLines = [];
        this.lines.forEach((item) => {
          this.allLines.push([item.start, item.end]);
        });
        this.$store.commit("updateLines", this.allLines);
        // console.log(this.lines);
      }
      document.querySelector("#main").removeChild(delElement);
      const type = delElement.getAttribute("flag");
      if (type === "0") {
        this.$message.success("数据集 删除成功!");
        this.createLog("数据集 删除成功!");
      } else if (type === "1") {
        this.$message.success("数据加工 删除成功!");
        this.createLog("数据加工 删除成功!");
      } else if (type === "2") {
        this.$message.success("算法模型 删除成功!");
        this.createLog("算法模型 删除成功!");
      }
    },
    //算法模型右键选择字段
    chooseField() {
      const dom = document.getElementById(this.currentDomId);
      let flag = false;
      this.lines.forEach((item) => {
        if (item.end === dom) {
          flag = true;
        }
      });
      if (flag) {
        if (!this.currentData.id) {
          return this.$message.error("数据集未绑定数据");
        } else {
          this.showDialog = true;
        }
      } else {
        this.$message.error("当前未绑定数据集");
      }
    },
    showFileUpload() {
      this.dialogVisible = true;
    },
    beforeUpload(file) {
      const currentFileType = file.name.split(".")[1];
      const requiredType = this.fileForm.type;
      if (!requiredType.includes(currentFileType)) {
        this.$message.error("当前上传的文件类型不正确!");
        return false;
      }
      if (currentFileType === "txt" || currentFileType === "csv") {
        if (this.fileForm.spliter === "") {
          this.$message.error("请选择文件分隔符!");
          return false;
        }
      }
      this.fileList.push(file);
    },
    async uploadFile(param) {
      const formData = new FormData();
      formData.append("file", param.file);
      formData.append("jsonObj", JSON.stringify(this.fileForm));

      const res = await fileUpload(formData);
      if (res.respCode === 200) {
        this.$message.success(res.respMessage);
        this.currentData.id = res.respData.id;
        this.currentData.fileName = res.respData.fileName;
        this.currentData.title = "查看文件";
        this.createLog("文件上传成功");
        this.queryAllFileList();
      } else {
        this.$message.error(res.respMessage);
      }
    },
    handleChange(uploadFile, uploadFiles) {
      this.tempFileList.push(uploadFile);
    },
    manualUpload() {
      if (this.tempFileList.length === 0) {
        return this.$message.error("请先选择文件!");
      }
      this.$refs["upload-demo"].submit();
      this.tempFileList = [];
    },
    uploadSuccess(response, file, fileList) {
      this.fileList = fileList;
      this.dialogVisible = false;
      console.log(file);
      const mian = document.querySelector("#main");
      const list = mian.querySelectorAll(".aside-left-list");
      list.forEach((item) => {
        if (item.getAttribute("flag") === "0") {
          item.children[1].innerHTML = file.name;
          return;
        }
      });
    },
    //展示文件数据
    async showFileData() {
      this.currentData.keyList = [];
      this.currentData.valueList = [];
      if (this.currentData.type == "0") {
        //查看文件数据 0:文件 1:数据源
        const res = await showFileData(this.currentData);
        if (res?.respCode === 200) {
          this.showFileTableDialog = true;

          const keyList = res.respData.colList;
          const valuelist = res.respData.dataList;

          this.currentData.keyList = keyList;
          //数组转对象
          const newValueList = valuelist.map((item) => {
            const obj = {};
            for (let i = 0; i < keyList.length; i++) {
              obj[keyList[i]] = item[i];
            }
            return obj;
          });

          const len = this.$store.state.historys.length;
          if (len > 0) {
            this.currentData.valueList =
              this.$store.state.historys[len - 1].list;
          } else {
            this.currentData.valueList = newValueList;
            // console.log(this.currentData.valueList, 6666);
          }
        } else {
          this.$message.error("查询文件数据失败!");
        }
      } else {
        //查看数据源数据
        const res = await queryDsDataList(this.currentData);
        if (res?.respCode === 200) {
          this.showFileTableDialog = true;
          this.$message.success("查询数据源数据成功！");

          this.currentData.keyList = res.respData.colList;
          const len = this.$store.state.historys.length;
          if (len > 0) {
            this.currentData.valueList =
              this.$store.state.historys[len - 1].list;
          } else {
            this.currentData.valueList = res.respData.dataList;
          }
          this.currentData.total = res.respData.total;
          // console.log(this.currentData.valueList, 66766);
        } else {
          this.$message.error("查询数据源失败!");
        }
      }
    },

    async queryColumn() {
      let type = "RDB";
      if (this.currentData.type == 0) type = "FILE";
      let paramMap = {
        dsType: type,
        dsID: this.currentData.id,
      };
      const res = await queryDataSourceColumn(paramMap);
      if (res?.respCode === 200) {
        for (let item of res.respData) {
          item.id = Math.round(Math.random() * 100000);
          item.cols =
            (item.colComment ? item.colComment : item.colName) +
            "-" +
            item.colTypeText;
        }
        this.fieldOrignData = res.respData;
        // 深拷贝数组对象
        this.fieldData = this.fieldOrignData.map((obj) =>
          JSON.parse(JSON.stringify(obj))
        );
        for (const key in this.allData) {
          if (this.allData[key].flag == "0") {
            this.allData[key].config = {};
            this.allData[key].config.colsInfo = this.fieldData;
            this.allData[key].config.dataSourceID = paramMap.dsID;
            this.allData[key].config.dataSourceType = paramMap.dsType;
            // this.allData[key].currentData = this.currentData
          }
        }
      }
    },
    closeFieldSet() {
      this.showfieldDialog = false;
      this.fieldData = this.fieldOrignData.map((obj) =>
        JSON.parse(JSON.stringify(obj))
      );
    },
    handleSettingSelect(item) {
      if (item.colTypeName == "STRING") {
        item.colTypeText = "文本型";
        item.colType = "1";
      } else if (item.colTypeName == "NUMERIC") {
        item.colTypeText = "数值型";
        item.colType = "2";
      } else if (item.colTypeName == "ENUM") {
        item.colTypeText = "枚举型";
        item.colType = "4";
      } else {
        item.colTypeText = "日期型";
        item.colType = "3";
      }
      item.cols =
        (item.colComment ? item.colComment : item.colName) +
        "-" +
        item.colTypeText;
    },

    //重置文件上传数据
    restFileUpload() {
      this.fileList = [];
      if (this.$refs["upload-demo"]) {
        this.$refs["upload-demo"].clearFiles();
      }
      //重置数据集名字
      const main = document.querySelector("#main");
      const dsImg = main.querySelector(".dataSet");
      dsImg.nextElementSibling.innerHTML = "数据集";

      this.currentData.title = "";
      this.currentData.id = "";
      this.currentData.fileName = "";
      this.currentData.valueList = [];
      this.currentData.keyList = [];

      this.allData[this.currentDomId].config = {};

      this.createLog("已重置数据");
      this.$message.success("已重置数据");
    },
    navigateToDataView() {
      this.$router.push("/dataView");
    },
    //去数据加工页面
    dataProcess(e) {
      //获取到当前数据加工dom
      const dom = document.getElementById(this.currentDomId);
      let flag = false;
      this.lines.forEach((item) => {
        if (item.end === dom) {
          flag = true;
        }
      });
      if (flag) {
        if (!this.currentData.id) {
          return this.$message.error("数据集未绑定数据");
        }
        this.$router.push({
          path: "/processTable",
          query: {
            id: this.currentData.id,
            cloned: this.currentDomId,
            type: this.currentData.type,
          },
        });
      } else {
        this.$message.error("当前未绑定数据集");
      }
    },
    async queryAlgorithmModelList() {
      const resp = await getAlgorithmModelList({});
      this.AlgorithmModelList = resp?.respData || [];
    },
    //查询所有文件
    async queryAllFileList() {
      const resp = await queryAllFileList({ name: this.queryFileName });
      this.allFileList = resp?.respData || [];
    },
    //底部添加日志
    createLog(message) {
      const footer = document.querySelector("#footer");
      const log = document.createElement("div");
      log.className = "log";
      log.style.color = "rgb(21, 171, 255)";
      log.innerHTML = new Date().toLocaleString() + "&nbsp;&nbsp;" + message;
      const firstDom = footer.children[0];
      if (!firstDom) {
        footer.appendChild(log);
      } else {
        footer.insertBefore(log, firstDom);
      }
    },
    //清楚场景信息
    clearScene() {
      ElMessageBox.confirm("确定要清除整个场景吗?", "Warning", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          const main = document.querySelector("#main");
          const list = main.querySelectorAll(".aside-left-list");
          this.lines.forEach((item) => {
            item.remove();
          });
          this.lines = [];
          list.forEach((item) => {
            main.removeChild(item);
          });
          this.dataSetCount = 0;
          this.createLog("场景清除成功！");
          this.clearData();
        })
        .catch(() => {});
    },
    //保存场景信息
    async saveScene() {
      this.saveSceneForm = {};
      for (const nodeKey in this.allData) {
        if (this.allData[nodeKey].flag === "0") {
          if (!this.allData[nodeKey].config.dataSourceID) {
            return ElMessage({
              message: "请选择数据源",
              type: "error",
            });
          }
        }
      }
      let svgElements = document.body.querySelectorAll("body>svg.leader-line");
      const node = document.body;
      const positionInfo = this.getXandY([].concat.apply([], this.allLines));
      for (const item of svgElements) {
        let children = item.childNodes;
        // 处理 SVG子节点  children 透明度
        children.forEach(function (child) {
          //解决svg透明度问题
          child.style.opacity = 1;
        });
        const parentNode = item.parentNode;
        //去除空白字符
        let svg = item.outerHTML.trim();
        // 创建一个 canvas DOM元素
        let canvas = document.createElement("canvas");
        //设置 canvas 元素的宽高
        const svgStyle = item.getAttribute("style");
        canvas.setAttribute("style", svgStyle);
        canvas.style.position = "absolute";
        let ctx = canvas.getContext("2d");

        const v = Canvg.fromString(ctx, svg);
        await v.render();

        // parentNode.removeChild(item);
        parentNode.appendChild(canvas);
      }
      let pic = await html2canvas(node, {
        useCORS: true,
        x: positionInfo.left,
        y: positionInfo.top,
        width: positionInfo.width + 70,
        height: positionInfo.height + 80,
        allowTaint: true,
        // windowHeight:height,
        // dpi: window.devicePixelRatio * 4,//设备像素比
        // windowWidth:document.body.scrollWidth,
        // backgroundColor: "#000"
      });
      const link = pic.toDataURL("image/jpg");
      document.querySelectorAll("body canvas").forEach((item) => {
        item.remove();
      });
      // this.exportPicture(link, "文件名");
      this.screenPic = link;
      this.saveSceneDialog = true;
    },
    //获取一个dom数组，返回他们的最小top和left
    getXandY(domArr = []) {
      let top = 2000,
        left = 2000,
        width = 0,
        height = 0;
      domArr.forEach((e, i) => {
        if (i > 0) {
          const b =
            e.getBoundingClientRect().bottom -
            domArr[i - 1].getBoundingClientRect().bottom;
          const r =
            e.getBoundingClientRect().right -
            domArr[i - 1].getBoundingClientRect().right;
          if (Math.abs(b) > height) {
            height = Math.abs(b);
          }
          if (Math.abs(r) > width) {
            width = Math.abs(r);
          }
        }
        const x = e.getBoundingClientRect().left;
        const y = e.getBoundingClientRect().top;
        if (x < left) {
          left = x;
        }
        if (y < top) {
          top = y;
        }
      });

      return { top, left, width, height };
    },

    //图片下载
    exportPicture(link, name = "未命名文件") {
      const file = document.createElement("a");
      file.style.display = "none";
      file.href = link;
      file.download = decodeURI(name);
      document.body.appendChild(file);
      file.click();
      document.body.removeChild(file);
    },
    //还原data属性
    clearData() {
      this.dataSetCount = 0;
      this.currentData.title = "";
      this.currentData.id = "";
      this.currentData.fileName = "";
      this.currentData.valueList = "";
      this.currentData.keyList = "";
    },
    //切换文件
    toggleFileData(event, name) {
      //存储选择的文件id和name
      this.currentData.title = "查看文件";
      this.currentData.type = 0;
      //处理文件的平均值
      if (this.currentData.id == event.target.id) {
        this.currentData.id = event.target.id;
      } else {
        this.$store.state.avg = [];
        this.$store.state.historys = [];
        this.currentData.id = event.target.id;
      }
      this.currentData.fileName = name;

      //改名
      const a = this.currentDomId;
      const textDom = document.getElementById(a);
      textDom.lastElementChild.innerHTML = this.currentData.fileName;
      this.createLog("已切换文件数据");
      this.$message.success("已切换文件数据");
      this.queryColumn();
    },
    async getDataModelList() {
      try {
        const res = await getDataModelList({});
        if (res?.respCode == 200) {
          this.dsData = res.respData;
        }
      } catch (e) {
        ElMessage({
          message: e.respMessage,
          type: "error",
        });
      }
    },
    //切换数据源
    toggledsData(obj, node) {
      let nodeType = node.data.nodeType;
      if (nodeType !== "0") {
        //添加背景色的类名
        const list = document.querySelectorAll(".fileItem");
        list.forEach((item) => {
          item.classList.remove("active");
        });

        this.currentData.title = "查看数据";
        this.currentData.type = 1;
        // this.currentData.id = node.data.nodeId;
        //处理了数据源的平均值
        if (this.currentData.id == node.data.nodeId) {
          this.currentData.id = node.data.nodeId;
        } else {
          this.$store.state.avg = [];
          this.$store.state.historys = [];
          this.currentData.id = node.data.nodeId;
        }
        this.currentData.fileName = node.data.nodeName;

        //改名
        const main = document.querySelector("#main");
        const dsImg = main.querySelector(".dataSet");
        dsImg.nextElementSibling.innerHTML = node.data.nodeName;
        dsImg.parentNode.title = this.currentData.fileName;
        this.$message.success("已切换数据源数据");
        this.createLog("已切换数据源数据");
        this.queryColumn();
      }
    },
    handleSizeChange(number) {
      this.currentData.pageSize = number;
      this.showFileData();
    },
    handleCurrentChange(number) {
      this.currentData.currentPage = number;
      this.showFileData();
    },
    prevPage(number) {
      this.showFileData();
    },
    nextPage(number) {
      this.showFileData();
    },
    getPicURL(name) {
      const type = name.split(".")[1];
      if (type === "xlsx" || type === "xls") return this.picURL.excel;
      if (type === "txt") return this.picURL.txt;
      if (type === "csv") return this.picURL.csv;
    },
    fitHeaderLength(name) {
      let length = name.length;
      console.log(name, name.length);
      return length * 25 + "px";
    },
    //保存场景的取消按钮
    closeSaveScene() {
      this.saveSceneForm = {};
      this.saveSceneDialog = false;
    },
    //保存场景的确定按钮
    async confirmSaveScene() {
      const params = {};

      const process = JSON.parse(localStorage.getItem("vuex")).avg[0];
      for (const processKey in process) {
        this.allData[processKey].config = process[processKey];
      }

      const allDataObj = Object.assign({}, this.allData);
      const linesObj = Object.assign({}, this.allData.lines);
      allDataObj.lines = undefined;
      params.sceneInfo = { ...this.saveSceneForm, viewImage: this.screenPic };
      params.nodesInfo = allDataObj;
      params.linesInfo = {};
      params.sceneID = this.id;
      for (const key in linesObj) {
        params.linesInfo[key] = {
          startNode: linesObj[key].startNode,
          stopNode: linesObj[key].stopNode,
        };
      }

      try {
        const res = await saveSceneDefine(params);
        this.sceneId = res?.respData;
        this.saveSceneDialog = false;
        this.saveSceneForm = {};
        ElMessage({
          message: res?.respMessage,
          type: "success",
        });
      } catch (e) {
        ElMessage({
          message: e.respMessage,
          type: "error",
        });
      }
    },
    //获取场景详情
    async querySceneDefine() {
      try {
        const res = await getSceneDefine({ sceneID: this.id });
        if (res?.respData) {
          this.allData = Object.assign({}, res.respData.nodesInfo);
          this.allData.lines = res.respData.linesInfo;
          this.saveSceneForm = res.respData.sceneInfo;
          this.renderAllData = Object.assign({}, res.respData.nodesInfo);
          const linesTemp = Object.assign({}, res.respData.linesInfo);
          let linesTempArr = [];
          for (const line in linesTemp) {
            await this.$nextTick(() => {
              linesTempArr.push([
                document.getElementById(linesTemp[line].startNode),
                document.getElementById(linesTemp[line].stopNode),
              ]);
              if (Object.keys(this.renderAllData).length > 0) {
                this.createLine(
                  document.getElementById(linesTemp[line].startNode),
                  document.getElementById(linesTemp[line].stopNode),
                  false
                );
              }
            });
          }
          for (const key in this.renderAllData) {
            if (this.renderAllData[key].flag == 0) {
              this.dataSetCount += 1;
              this.currentData.id = this.renderAllData[key].config.dataSourceID;
              this.currentData.type =
                this.renderAllData[key].config.dataSourceType === "FILE"
                  ? 0
                  : 1;
              this.currentData.fileName = this.getDataSourceName(
                this.currentData.id
              );
              await this.queryColumn();
            } else if (this.renderAllData[key].flag == 2) {
              await this.getModelConfig(this.renderAllData[key].AlgorithmId);
              //算法模型穿梭框回显
              this.configParams[key] = {
                varList: this.renderAllData[key].config.varList,
                destVar: this.renderAllData[key].config.destVar,
              };
            } else if (this.renderAllData[key].flag == 1) {
              this.$store.dispatch("setnewAvgdatas", [
                { [key]: this.renderAllData[key].config },
              ]);
              // const localVue = JSON.parse(localStorage.getItem("vuex"));
              // localVue.avg = [{ [key]: this.renderAllData[key].config }];
              // localStorage.setItem("vuex", JSON.stringify(localVue));
              // console.log(localVue.avg);
            }

            // this.configParams[key].destVar = this.renderAllData[key].destVar
            this.setNodeConfig(document.getElementById(key));
          }
          this.allLines = linesTempArr;
        }
      } catch (e) {
        console.error(e);
      }
    },
    //获得图片的url
    getNodePicUrl(value, flag, getName) {
      let name = "linearRegression.png";
      if (flag == "0") {
        if (getName) {
          return this.getDataSourceName(value.config.dataSourceID);
        }
        return require("../../assets/images/dataSet.svg");
      } else if (flag == "1") {
        if (getName) return "数据加工";
        return require("../../assets/images/dataProcessing.svg");
      } else {
        const algorithmName = this.getRightAlgorithmName(value.AlgorithmId);
        if (getName) {
          return algorithmName.name;
        }
        if (name) {
          return require(`@/assets/images/AlgorithmMode/${algorithmName.picName}.png`);
        }
      }
    },
    //关闭
    close() {
      this.$router.push({ path: "/sceneView" });
      this.$store.state.avg = [];
      this.$store.state.historys = [];
      this.$store.state.newAvg = [];
    },
    //获取数据源名称
    getDataSourceName(dataSourceID) {
      let a = "";
      this.allFileList.forEach((i) => {
        if (i.id === dataSourceID) {
          a = i.name;
        }
      });
      return a;
    },
    //render数据，渲染结束后拖动
    renderDragEnd(event) {
      const dom = event.srcElement;
      const posY = this.mouseY - dom.offsetHeight / 2 + "px";
      const posX = this.mouseX - dom.offsetWidth / 2 + "px";
      this.renderAllData[dom.id].posY = posY;
      this.renderAllData[dom.id].posX = posX;
    },
  },
  mounted() {
    const main = document.querySelector("#main");
    window.addEventListener("click", () => {
      this.rightClickMenuType = 0;
    });
    document
      .querySelectorAll(".aside-left-list")[2]
      .addEventListener("click", () => {
        this.isShowAlgorithmModelList = true;
      });
    document.querySelector("#main").addEventListener("mouseover", () => {
      this.isShowAlgorithmModelList = false;
    });

    main.addEventListener("contextmenu", (e) => {
      e.preventDefault();
      const main = document.querySelector("#main");
      const list = main.querySelectorAll(".aside-left-list");
      list.forEach((item) => {
        item.classList.remove("active");
      });
      if (this.endElement?.className === "empty") {
        this.lines[this.lines.length - 1].remove();
        this.lines.pop();
        this.startElement = null;
        this.endElement = null;
      }
    });

    main.addEventListener("mousemove", (e) => {
      const empty = main.querySelector(".empty");
      const asideLeft = document.querySelector("#aside-left");

      empty.style.left = e.clientX - asideLeft.offsetWidth + "px";
      empty.style.top = e.clientY - asideLeft.offsetTop + "px";
      if (this.lines.length !== 0) {
        this.lines.forEach((item) => item.position());
      }
    });
  },
  created() {
    this.queryAlgorithmModelList();
    this.queryAllFileList();
    // setTimeout(() => {
    //   this.exeResultdialog = true;
    //   console.log(5555);
    // }, 1000);
    // this.getDataModelList();
  },
  watch: {
    currentDomId(newValue, oldValue) {
      if (this.allModelConfig[newValue]) {
        this.paramsRules = this.allModelConfig[newValue].paramsRules;
        this.paramsForm = this.allModelConfig[newValue].paramsForm;
        this.modelConfig = this.allModelConfig[newValue].modelConfig;
      }
    },
    paramsForm: {
      deep: true,
      handler(newValue, oldValue) {
        let formValue = this.allData[this.currentDomId];
        if (formValue?.config) {
          this.allData[this.currentDomId].config = Object.assign(
            formValue.config,
            newValue
          );
        }
      },
    },
    id(newValue, oldValue) {
      this.sceneId = newValue;
    },
  },
};
</script>

<style lang="scss" scoped>
.container {
  width: 100%;
  height: 100%;
  color: black;

  .header {
    border-bottom: 1px solid rgb(21, 171, 255);
  }

  .right_algorithm_container {
    .algorithm_title {
      padding: 7px;
    }

    .algorithm_line {
      border-top: 1px solid #15abff;
    }
  }

  #aside-left {
    border-right: 1px solid rgb(21, 171, 255);
    box-sizing: border-box;

    .aside-left-list {
      width: 90px;
      height: 55px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      margin: 20px auto;

      img {
        width: 30px;
      }

      cursor: pointer;
    }
  }

  #algorithmModel-list {
    position: absolute;
    width: 380px;
    height: 600px;
    left: 100px;
    z-index: 9999;
    color: rgb(128, 128, 255);
    background-color: white;
    border: solid rgb(128, 128, 255) 1px;

    .algorithmModel-list-children {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      text-align: center;

      .title {
        color: rgb(128, 128, 255);
        margin-left: 10px;
      }
    }
  }

  #main {
    padding: 0;
    position: relative;
    overflow: hidden;
    z-index: 100;

    .active {
      border: 1px solid rgb(21, 171, 255);
    }

    .aside-left-list {
      cursor: pointer;
      text-align: center;
      width: 80px;
      height: 70px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      background: #fff;

      img {
        width: 30px;
      }

      .dataSetDiv {
        width: 75px;
        text-align: center;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap; /* 防止换行 */
      }
    }

    #dsSet-right-click {
      width: 90px;
      color: black;
      border: 1px solid;
      border-radius: 5px;
      z-index: 22;

      .children {
        border-top: 1px solid;
        text-align: center;
      }

      .children:nth-child(1) {
        border-top: none;
      }

      .children:hover {
        background-color: rgb(21, 171, 255);
        cursor: pointer;
      }
    }

    .empty {
      position: absolute;
      left: 0;
      top: 0;
      width: 1px;
      height: 1px;
      background-color: red;
    }
  }

  #aside-right {
    border-left: 1px solid rgb(21, 171, 255);
    overflow: hidden;
    height: 100%;
    background-color: white;

    .myIcon {
      margin: 5px;
      display: flex;
      width: 80px;
      justify-content: space-between;

      .el-icon {
        cursor: pointer;
      }
    }

    .ds-right {
      height: 100%;

      .el-input {
        margin: 5px;
        width: 190px;
      }

      .title {
        font-size: 18px;
        background-color: rgb(21, 171, 255);
        color: white;
        text-align: center;
      }

      .fileList {
        width: 100%;
        height: 41.5%;
        overflow-y: auto;
        overflow-x: auto;

        .active {
          background-color: rgb(236, 245, 255);
        }

        .fileItem {
          padding: 5px 22px;
          font-size: 14px;
          color: #606266;
          cursor: pointer;
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
        }

        .fileItem:hover {
          background-color: rgb(236, 245, 255);
        }

        .custom-tree-node {
          .tree_nodei_icon {
            margin-right: 6px;
          }

          .tree_nodei_img {
            vertical-align: middle;
          }
        }

        ::v-deep .el-tree-node:focus > .el-tree-node__content {
          background-color: rgb(236, 245, 255);
        }
      }
    }
  }

  #footer {
    border-top: 1px solid rgb(21, 171, 255);
    padding: 5px;
    overflow: auto;
    background-color: white;
  }
}

#fileDialog {
  .el-dialog__header {
    text-align: left;
    font-weight: 700;
  }

  .el-dialog__body {
    padding: 0;

    .el-divider {
      margin: 10px 0px;
    }

    .span {
      display: block;
      margin-left: 20px;
      margin-top: 10px;
      text-align: left;
    }

    .father {
      .pic {
        width: 70px;
      }

      .fileRadio1 {
        display: flex;
        width: 60%;
        margin: 20px auto;
        justify-content: space-between;

        .fileRadio1-demo {
          display: flex;
          flex-direction: column;
          align-items: center;
        }
      }

      .fileRadio2 {
        margin-left: 59px;
      }

      .fileRadio3 {
        display: flex;
        margin-left: 135px;
      }

      .upload-demo {
        margin-top: 20px;
        margin-left: 60px;
        width: 300px;
      }
    }
  }

  .el-dialog__footer {
    .el-divider {
      margin: 10px 0px;
    }
  }
}

.dscolor {
  background-color: #fff;
}

.back {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  // padding-right: 20px;
  box-sizing: border-box;

  .icon {
    cursor: pointer;
    color: #808080;

    &:hover {
      color: skyblue;
    }
  }
}

.header {
  height: 40px;
  border-bottom: solid 1px #dedede;
}

::v-deep .el-dialog__body {
  padding: 0;
}

.fieldDialog {
  .fieldSpan {
    display: block;
    width: 80px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  .fieldCol {
    padding: 10px;
    display: flex;
    align-items: center;
    justify-content: center;

    ::v-deep .fieldInput .el-input__inner {
      text-align: right;
    }

    .fieldSelect {
      width: 200px;
      padding-left: 15px;
      background-color: #fff;
    }
  }
}

.el-pagination {
  display: flex;
  justify-content: center;
}
.icon-del {
  color: red;
}
</style>